package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"
)

func Check() {

	var config string
	flag.StringVar(&config, "c", "", "配置文件路径")
	// 把用户传递的命令行参数解析为对应变量的值
	flag.Parse()

	if config == "" {
		panic("配置文件不可以空")
	}
	configFileContent, err := os.ReadFile(config)
	if err != nil {
		panic(err)
	}
	var conf Config
	json.Unmarshal(configFileContent, &conf)
	if err != nil {
		panic(err)
	}

	buyerIndex := 0
	//开始抢票
	for {
		time.Sleep(4 * time.Second)
		tickList := GetTicketList(conf.Header)

		sprint := fmt.Sprintf("查询余票数量 %v ：%v", time.Now().Format("2006-01-02 15:04:05"), tickList.GetRemainMap())
		fmt.Println(sprint)
		if conf.TickTypeID != 0 {
			remainNum := tickList.GetRemainNumByTickId(conf.TickTypeID)
			if remainNum > 0 {
				//获取购买人列表
				buyerList := GetBuyerList(conf.Header)
				BuyerInfo := buyerList.GetOneBuyer(&buyerIndex)

				//下单
				buyRes := BuyNow(conf.Header, conf.TickTypeID, BuyerInfo.ID)

				fmt.Sprintln("下单结果：%v", buyRes)
			}
		}

	}
}

/*
 获取余票数量
*/
func GetTicketList(header map[string]string) *ResponseGetTickList {
	url := "https://www.allcpp.cn/allcpp/ticket/getTicketTypeList.do?eventMainId=1074"
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return nil
	}
	req.Header.Add("authority", "www.allcpp.cn")
	req.Header.Add("accept", "application/json, text/plain, */*")
	req.Header.Add("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Add("cache-control", "no-cache")
	req.Header.Add("cookie", "Hm_lvt_75e110b2a3c6890a57de45bd2882ec7c=1682046786; token=REvR5a13NVjGsMQ5vWEMLTtVTjNeF5gLIyUqI2a/M3c9M0rCE6wJ0Q0NhO2DJuXSzLur41+gYvQg1xi9D2TrhX+bgwef35sswtufzm8hA12Aywv84wBmTWcigueSaFahrptFE0s7ZFCk+fNX0m6uVUXBQV0Q1kc39259SQvKONg=; JALKSJFJASKDFJKALSJDFLJSF=2392071151b782ecc8ab784857bd845d3915e9a36f10.92.108.68_10522398; JSESSIONID=31CD3FDBBEB56AF9765434CE9EFD762C; Hm_lpvt_75e110b2a3c6890a57de45bd2882ec7c=1682090468; JSESSIONID=B193B85118BCBCA29F970CB08C2F72E8")
	req.Header.Add("origin", "https://cp.allcpp.cn")
	req.Header.Add("pragma", "no-cache")
	req.Header.Add("referer", "https://cp.allcpp.cn/")
	req.Header.Add("sec-ch-ua", "\"Chromium\";v=\"112\", \"Google Chrome\";v=\"112\", \"Not:A-Brand\";v=\"99\"")
	req.Header.Add("sec-ch-ua-mobile", "?0")
	req.Header.Add("sec-ch-ua-platform", "\"macOS\"")
	req.Header.Add("sec-fetch-dest", "empty")
	req.Header.Add("sec-fetch-mode", "cors")
	req.Header.Add("sec-fetch-site", "same-site")
	req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")

	for key, val := range header {
		req.Header.Set(key, val)
	}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	tickList := new(ResponseGetTickList)
	json.Unmarshal(body, tickList)
	return tickList

}

//获取购票人列表
func GetBuyerList(header map[string]string) *ResponseBuyerList {

	url := "https://www.allcpp.cn/allcpp/user/purchaser/getList.do"
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return nil
	}
	req.Header.Add("authority", "www.allcpp.cn")
	req.Header.Add("accept", "application/json, text/plain, */*")
	req.Header.Add("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Add("cache-control", "no-cache")
	req.Header.Add("cookie", "Hm_lvt_75e110b2a3c6890a57de45bd2882ec7c=1682046786; token=REvR5a13NVjGsMQ5vWEMLTtVTjNeF5gLIyUqI2a/M3c9M0rCE6wJ0Q0NhO2DJuXSzLur41+gYvQg1xi9D2TrhX+bgwef35sswtufzm8hA12Aywv84wBmTWcigueSaFahrptFE0s7ZFCk+fNX0m6uVUXBQV0Q1kc39259SQvKONg=; JALKSJFJASKDFJKALSJDFLJSF=2392071151b782ecc8ab784857bd845d3915e9a36f10.92.108.68_10522398; JSESSIONID=31CD3FDBBEB56AF9765434CE9EFD762C; Hm_lpvt_75e110b2a3c6890a57de45bd2882ec7c=1682087583; JSESSIONID=AD3815D6B19E5469E417C619703BEFB7")
	req.Header.Add("origin", "https://cp.allcpp.cn")
	req.Header.Add("pragma", "no-cache")
	req.Header.Add("referer", "https://cp.allcpp.cn/")
	req.Header.Add("sec-ch-ua", "\"Chromium\";v=\"112\", \"Google Chrome\";v=\"112\", \"Not:A-Brand\";v=\"99\"")
	req.Header.Add("sec-ch-ua-mobile", "?0")
	req.Header.Add("sec-ch-ua-platform", "\"macOS\"")
	req.Header.Add("sec-fetch-dest", "empty")
	req.Header.Add("sec-fetch-mode", "cors")
	req.Header.Add("sec-fetch-site", "same-site")
	req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
	for key, val := range header {
		req.Header.Set(key, val)
	}

	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	buyerList := new(ResponseBuyerList)
	json.Unmarshal(body, buyerList)
	return buyerList
}

/*
下单
*/
func BuyNow(header map[string]string, tickId, buyerId int) *ResponseAddOrder {
	//url := "https://www.allcpp.cn/allcpp/ticket/buyTicketAlipay.do?ticketTypeId=1905&count=1&nonce=bMxM4YKzKQ24Nz46NejHt4TZdjr6ZQ4C&timeStamp=1682087626&sign=cc286673d67e94627b22fe3e437e51f2&purchaserIds=1432530"
	url := "https://www.allcpp.cn/allcpp/ticket/buyTicketAlipay.do?ticketTypeId=%d&count=1&nonce=bMxM4YKzKQ24Nz46NejHt4TZdjr6ZQ4C&timeStamp=1682087626&sign=cc286673d67e94627b22fe3e437e51f2&purchaserIds=%d"
	url = fmt.Sprintf(url, tickId, buyerId)
	method := "POST"

	payload := strings.NewReader(`{}`)

	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return nil
	}
	req.Header.Add("authority", "www.allcpp.cn")
	req.Header.Add("accept", "application/json, text/plain, */*")
	req.Header.Add("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Add("cache-control", "no-cache")
	req.Header.Add("content-type", "application/json;charset=UTF-8")
	req.Header.Add("cookie", "Hm_lvt_75e110b2a3c6890a57de45bd2882ec7c=1682046786; token=REvR5a13NVjGsMQ5vWEMLTtVTjNeF5gLIyUqI2a/M3c9M0rCE6wJ0Q0NhO2DJuXSzLur41+gYvQg1xi9D2TrhX+bgwef35sswtufzm8hA12Aywv84wBmTWcigueSaFahrptFE0s7ZFCk+fNX0m6uVUXBQV0Q1kc39259SQvKONg=; JALKSJFJASKDFJKALSJDFLJSF=2392071151b782ecc8ab784857bd845d3915e9a36f10.92.108.68_10522398; JSESSIONID=31CD3FDBBEB56AF9765434CE9EFD762C; Hm_lpvt_75e110b2a3c6890a57de45bd2882ec7c=1682087583; JSESSIONID=36967B3FFAB94838111E52626BCE794F")
	req.Header.Add("origin", "https://cp.allcpp.cn")
	req.Header.Add("pragma", "no-cache")
	req.Header.Add("referer", "https://cp.allcpp.cn/")
	req.Header.Add("sec-ch-ua", "\"Chromium\";v=\"112\", \"Google Chrome\";v=\"112\", \"Not:A-Brand\";v=\"99\"")
	req.Header.Add("sec-ch-ua-mobile", "?0")
	req.Header.Add("sec-ch-ua-platform", "\"macOS\"")
	req.Header.Add("sec-fetch-dest", "empty")
	req.Header.Add("sec-fetch-mode", "cors")
	req.Header.Add("sec-fetch-site", "same-site")
	req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
	for key, val := range header {
		req.Header.Set(key, val)
	}

	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	//fmt.Println(string(body))
	response := new(ResponseAddOrder)
	json.Unmarshal(body, response)
	return response
}

/*
todo
签名算法
*/
func sign() {

}

/*
配置文件
*/
type Config struct {
	Header     map[string]string `json:"header"`
	TickTypeID int               `json:"tick_type_id"`
}

/*
获取余票列表 返回参数
*/
type ResponseGetTickList struct {
	TicketMain     TicketMain       `json:"ticketMain"`
	TicketTypeList []TicketTypeList `json:"ticketTypeList"`
}
type TicketMain struct {
	ID               int         `json:"id"`
	Name             string      `json:"name"`
	EventName        string      `json:"eventName"`
	Description      string      `json:"description"`
	EventDescription string      `json:"eventDescription"`
	CoverPicID       int         `json:"coverPicId"`
	CoverPicURL      string      `json:"coverPicUrl"`
	PicID            int         `json:"picId"`
	Priority         int         `json:"priority"`
	Enabled          int         `json:"enabled"`
	EventMainID      int         `json:"eventMainId"`
	Type             int         `json:"type"`
	CreateTime       int64       `json:"createTime"`
	UpdateTime       int64       `json:"updateTime"`
	ConfirmableVO    interface{} `json:"confirmableVO"`
}
type TicketTypeList struct {
	ID                int         `json:"id"`
	EventID           int         `json:"eventId"`
	TicketMainID      int         `json:"ticketMainId"`
	TicketName        string      `json:"ticketName"`
	TicketAttribute   int         `json:"ticketAttribute"`
	TicketPrice       int         `json:"ticketPrice"`
	PurchaseNum       int         `json:"purchaseNum"`
	RemainderNum      int         `json:"remainderNum"`
	LockNum           int         `json:"lockNum"`
	Session           int         `json:"session"`
	SellStartTime     int64       `json:"sellStartTime"`
	SellEndTime       int64       `json:"sellEndTime"`
	TicketDescription string      `json:"ticketDescription"`
	TicketGPStartTime int64       `json:"ticketGPStartTime"`
	TicketGPEndTime   int64       `json:"ticketGPEndTime"`
	RealNameAuth      bool        `json:"realnameAuth"`
	Square            string      `json:"square"`
	CreateTime        interface{} `json:"createTime"`
	UpdateTime        int64       `json:"updateTime"`
}

/*
通过票id 获取余票数量
*/
func (this *ResponseGetTickList) GetRemainNumByTickId(TickId int) (remainNum int) {
	for _, tickInfo := range this.TicketTypeList {
		if tickInfo.ID == TickId {
			return tickInfo.RemainderNum
		}
	}
	return 0
}

/*
通过票id 获取余票数量
*/
func (this *ResponseGetTickList) GetRemainMap() map[int]int {
	tickRemain := make(map[int]int)
	for _, tickInfo := range this.TicketTypeList {
		tickRemain[tickInfo.ID] = tickInfo.RemainderNum
	}
	return tickRemain
}

/*
购票人列表
*/
type ResponseBuyerList []BuyerInfo

type BuyerInfo struct {
	ID        int    `json:"id"`
	Realname  string `json:"realname"`
	Idcard    string `json:"idcard"`
	Mobile    string `json:"mobile"`
	ValidType int    `json:"validType"`
}

/*
通过票id 获取余票数量
*/
func (this *ResponseBuyerList) GetOneBuyer(buyerListIndex *int) (buyerInfo BuyerInfo) {
	buyerList := []BuyerInfo(*this)
	buyerLen := len(buyerList)
	*buyerListIndex = (*buyerListIndex) % buyerLen

	buyerInfo = buyerList[*buyerListIndex]
	*buyerListIndex++

	return buyerInfo
}

/*
下单接口返回结构
*/
type ResponseAddOrder struct {
	ErrorCode int    `json:"errorCode"`
	Message   string `json:"message"`
	IsSuccess bool   `json:"isSuccess"`
}
